package com.chenxy.gateway.filter;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.chenxy.common.exception.impl.CommonExceptionEnum;
import com.chenxy.common.result.Res;
import com.chenxy.common.utils.JwtUtils;
import com.chenxy.gateway.feign.UserCenterFeignClients;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;

@Component
public class UserGlobalFilter implements GlobalFilter, Ordered {
    @Resource
    private UserCenterFeignClients userCenterFeignClients;

    @Value("${unOpenCheckToken}")
    private boolean unOpenCheckToken;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //是否开启token校验
        if (unOpenCheckToken){
            exchange.getRequest().mutate().header("userid","0").build();
            return chain.filter(exchange);
        }
        ServerHttpResponse response = exchange.getResponse();
        String token = exchange.getRequest().getHeaders().getFirst("token");
        //获取请求路径
        String url = String.valueOf(exchange.getRequest().getPath());
        /**
         * 登录，登出接口直接跳过，不做token校验
         */
        if(url.indexOf("/login/in")>=0 && url.indexOf("/login/out")==-1){
            return chain.filter(exchange);
        }

        if(StringUtils.isBlank(token))
        {
            return blockRequestWithMsg(response,CommonExceptionEnum.TOKEN_IS_NULL);
        }
        //解析token,根据token获得用户信息
        Claims claims = JwtUtils.checkJwtToken(token);
        Integer userid = (Integer) claims.get("userid");
        //header中放入userid
        exchange.getRequest().mutate().header("userid",String.valueOf(userid)).build();

        //Res<Boolean> canRequest = userCenterFeignClients.isCanRequest(userid, url);
        //继续往下执行
        return chain.filter(exchange);
    }

    /**
     * 网关出现token认证错误和鉴权错误，返回前端信息
     * @param response
     * @param commonExceptionEnum
     * @return
     */
    private Mono<Void> blockRequestWithMsg(ServerHttpResponse response, CommonExceptionEnum commonExceptionEnum) {
        Res data = Res.fail(commonExceptionEnum.getErrCode(), commonExceptionEnum.getErrMsg());
        DataBuffer buffer = response.bufferFactory().wrap(JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8));
        response.setStatusCode(HttpStatus.OK);
        //指定编码，否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        Mono<Void> voidMono = response.writeWith(Mono.just(buffer));
        return voidMono;
    }


    @Override
    public int getOrder() {
        return -101;
    }
}
